<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>

  <body>
    <script>
      /**
       * 单例模式改造
       * 要把instance变量保存下来,放在闭包里面，只要闭包不销毁，这个变量会一直在内存中
       * single是一个函数，可以判断，可以返回
       * 闭包的作用：延长变量的声明周期
       * 以闭包的形式来执行一段代码
       * 为了保存构造函数，也把它写在闭包里面--2
       * 如果你觉得使用需要new关键字,那么你就直接写--3
       *      例如：const p1 = new Person()
       *            const p2 = new Person()
       */

      // 1.一开始写在外面的构造函数
      // function Person() {
      //     this.name = "kack"
      // }

      const single = (function () {
        // 2、把构造函数放在里面
        // 真实构造函数体
        function Person(name, age, gender) {
          this.name = name; //接受参数
          this.age = age;
          this.gendger = gender;
        }

        Person.prototype.sayhi = function () {
          console.log("hi~");
        };//标准函数体

        //这个变量因为在一个不会被销毁的函数执行空间里面
        //所以会一直存在
        let instance = null;
        // 群居变量接受的是这个函数
        return function single(...arg) {
          if (!instance) instance = new Person(...arg);
          return instance;
        };
      })();

      //如果将const single改成Person， const p2 = single()改成 const p2 =Person()， const p1 = single()改成 const p1 =Person()，
      //访问的其实还是全局的这个const Person = ……而不会到函数里面去找Person()，并且打印结果依旧不变、
      //相当于只是换了一个名字而已
      const p1 = single("Mike", 18, "男"); //传参---4
      const p2 = single("rose", 15, "女"); //这里传参并不会改变结果，因为instance，也就是Person存在了，所以他不会执行if里面的语句了，只会执行single那一层
      //所以单例模式不会在这里传参数了，因为传多少遍都是一样的

      console.log(p1, p2); //person:{name:"jack"},person:{name:"jack"}
      console.log(p1 === p2); //true
    </script>
  </body>
</html>
